/**
 * $version:  0.1 
 * $Date: 2011-01-21 
 *
 * Copyright (C) 2010-2011 Jawa Software. All rights reserved.
 *
 */
package org.jawa.admin;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 菜单仓库组件。
 * 
 * @author Y-N
 * 
 */
public class MenuRepository implements Serializable {

	private static final long serialVersionUID = 951995913749344170L;

	private static final Logger Log = LoggerFactory
			.getLogger(MenuRepository.class);

	// 所有菜单组件
	protected LinkedHashMap menus = new LinkedHashMap();

	/**
	 * 返回所有菜单组件编码。
	 * 
	 * @return
	 */
	public Set getMenuIds() {
		return menus.keySet();
	}

	/**
	 * 返回顶级菜单组件。
	 */
	public List<MenuComponent> getTopMenus() {
		List<MenuComponent> topMenus = new ArrayList<MenuComponent>();
		if (menus == null) {
			Log.warn("菜单仓库中不存在菜单项!");
			return topMenus;
		}

		for (Iterator it = menus.keySet().iterator(); it.hasNext();) {
			Long menuId = (Long) it.next();
			MenuComponent menu = getMenu(menuId);
			if (null != menu.getParent() && menu.getParent().getMenuId() == 0L) {
				topMenus.add(menu);
			}
		}
		return topMenus;
	}

	/**
	 * 返回下级菜单。
	 */
	public List<MenuComponent> getChildrenMenus(Long menuParent) {
		List<MenuComponent> childrenMenus = new ArrayList<MenuComponent>();
		if (menus == null) {
			Log.warn("菜单仓库中不存在菜单项!");
			return childrenMenus;
		}

		for (Iterator it = menus.keySet().iterator(); it.hasNext();) {
			Long menuId = (Long) it.next();
			MenuComponent menu = getMenu(menuId);
			if (menuParent.equals(menu.getParent().getMenuId())) {
				childrenMenus.add(menu);
			}
		}
		return childrenMenus;
	}
	
	/**
	 * 返回顶级菜单组件数组。
	 * 
	 * @return 顶级菜单组件数组
	 */
	public MenuComponent[] getTopMenusAsArray() {
		List menuList = this.getTopMenus();
		MenuComponent[] menus = new MenuComponent[menuList.size()];
		for (int a = 0; a < menuList.size(); a++) {
			menus[a] = (MenuComponent) menuList.get(a);
		}

		return menus;
	}

	/**
	 * 返回顶组菜单列表。
	 * 
	 * @return List 顶组菜单列表
	 */
	public List getTopMenuIds() {
		List menus = this.getTopMenus();
		ArrayList names = new ArrayList();
		for (Iterator iterator = menus.iterator(); iterator.hasNext();) {
			MenuComponent menu = (MenuComponent) iterator.next();
			names.add(menu.getMenuId());
		}
		return names;
	}

	/**
	 * 获取菜单组件。
	 * 
	 * @param menuId
	 *            菜单组件编码
	 * @return 菜单组件
	 */
	public MenuComponent getMenu(Long menuId) {
		return (MenuComponent) menus.get(menuId);
	}

	/**
	 * 向菜单仓库中加入一个菜单组件。
	 * 
	 * @param menu
	 *            菜单组件
	 */
	public void addMenu(MenuComponent menu) {
		if (menus.containsKey(menu.getMenuId())) {
			Log.warn("菜单 '" + menu.getMenuName() + "' 已存在");
			List children = (getMenu(menu.getMenuId())).getComponents();
			if (children != null && menu.getComponents() != null) {
				for (Iterator it = children.iterator(); it.hasNext();) {
					MenuComponent child = (MenuComponent) it.next();
					menu.addMenuComponent(child);
				}
			}
		}
		menus.put(menu.getMenuId(), menu);
	}

	/**
	 * 移出一个菜单组件。
	 * 
	 * @param menuId
	 *            菜单组件编码
	 */
	public void removeMenu(Long menuId) {
		menus.remove(menuId);
	}

	/**
	 * 移出所有菜单组件。
	 */
	public void removeAllMenus() {
		menus.clear();
	}

	/**
	 * 返回指定菜单组件的深度。
	 * 
	 * @param menuId
	 *            菜单组件编码
	 * @return 菜单组件深度，如果没有找到返回 -1
	 */
	public int getMenuDepth(Long menuId) {
		MenuComponent menu = this.getMenu(menuId);
		if (menu == null)
			return -1;
		if (menu.getMenuComponents() == null)
			return 1;
		return menu.getMenuDepth();
	}

	/**
	 * 返回当前菜单组件的深度。
	 * 
	 * @return 菜单组件深度，如果没有找到返回 -1
	 */
	public int getMenuDepth() {
		int currentDepth = 0;

		List topMenus = this.getTopMenus();

		if (topMenus == null)
			return -1;
		for (Iterator menu = topMenus.iterator(); menu.hasNext();) {
			int depth = ((MenuComponent) menu.next()).getMenuDepth();
			if (currentDepth < depth)
				currentDepth = depth;
		}
		return currentDepth;
	}

}
